package com.newenergy.wisehome.services;

import android.content.Context;
import android.media.MediaPlayer;
import android.util.Log;
import android.widget.Toast;

import com.baidu.speech.EventListener;
import com.baidu.speech.EventManager;
import com.baidu.speech.EventManagerFactory;
import com.baidu.speech.asr.SpeechConstant;
import com.newenergy.wisehome.R;
import com.newenergy.wisehome.bd.RecogResult;
import com.newenergy.wisehome.config.AppManager;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;

public class BDSpeechManager  {
    public static final String TAG = "QBH";
    private MediaPlayer mp;//mediaPlayer对象
    private EventManager mAsr;
    private EventManager mWp;
    private Toast mToast;
    public int type = 0;
    private Context mContext;
//    "accept-audio-data":false,"disable-punctuation":false,
//    public String mParamsJson = "{\"accept-audio-volume\":true,\"pid\":1536}";


    public BDSpeechManager(Context context){
        mContext = context;
    }

    private void init() {
        // this是Activity或其它Context类
        mWp = EventManagerFactory.create(mContext, "wp");
        mWp.registerListener(wpListener);
        // this是Activity或其它Context类
        mAsr = EventManagerFactory.create(mContext, "asr");
        loadOffLineAsr();
        mAsr.registerListener(asrListener);

    }


    private void loadOffLineAsr() {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put(SpeechConstant.DECODER, 2);
        map.put(SpeechConstant.ASR_OFFLINE_ENGINE_GRAMMER_FILE_PATH, "assets:///baidu_speech_grammar.bsg");
        String json = new JSONObject(map).toString();
        mAsr.send(SpeechConstant.ASR_KWS_LOAD_ENGINE, json, null,0, 0);
    }




    public void startBDSpeech() {
        init();
        startWakeup();
        type = 0;
    }


    public void endBDSpeech() {
        Log.i(TAG, "onStop: 释放录音");
//        toast("释放录音");
        finishRecognize();
        type = 0;
    }

    public void finishRecognize(){
        if ( mAsr!=null){
            mAsr.send(SpeechConstant.ASR_STOP, null, null, 0, 0);
            mAsr.send(SpeechConstant.ASR_CANCEL, null, null, 0, 0);
            mAsr.send(SpeechConstant.ASR_KWS_UNLOAD_ENGINE, null, null, 0, 0);
            if (asrListener !=null){
                mAsr.unregisterListener(asrListener);
            }
            mAsr = null;
        }
        if ( mWp!=null) {
            mWp.send(SpeechConstant.WAKEUP_STOP, null, null, 0, 0);
            mWp.send(SpeechConstant.WAKEUP_UNLOAD_ENGINE, null, null, 0, 0);
            if (wpListener != null) {
                mWp.unregisterListener(wpListener);

            }
            mWp = null;
        }

    }


    public void startWakeup() {
        Log.i(TAG, "startWakeup: 启动唤醒");
        if (mWp != null) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put(SpeechConstant.WP_WORDS_FILE, "assets:///WakeUp.bin"); //唤醒词文件请去http://yuyin.baidu.com/wake下载
            String json = new JSONObject(map).toString();
//            String json = "{\"kws-file\":\"assets:///WakeUp.bin\"}";
            mWp.send(SpeechConstant.WAKEUP_START, json, null, 0, 0);
        }
    }



    public void stopWakeup() {
        if (mWp != null) {
            mWp.send(SpeechConstant.WAKEUP_STOP, null, null, 0, 0);
        }
    }



    public void startRecognize() {
        Log.i(TAG, "startRecognize:");
        if (mAsr!=null){
            String recognizeParams = getRecognizeParams();
//            String json = "{\"accept-audio-data\":false,\"disable-punctuation\":false,\"accept-audio-volume\":true,\"pid\":1536}";
            mAsr.send(SpeechConstant.ASR_START,recognizeParams , null, 0, 0);
        }
    }


    public String getRecognizeParams(){
             Map<String, Object> params = new HashMap<>();
//            String language = StorageHelper.getLanguage();
            String language = "cmn-Hans-CN";
            params.put(SpeechConstant.DECODER, 2);
            params.put(SpeechConstant.LANGUAGE, language);
            params.put(SpeechConstant.DISABLE_PUNCTUATION, true);
            params.put(SpeechConstant.VAD_ENDPOINT_TIMEOUT,800);
            params.put(SpeechConstant.VAD,SpeechConstant.VAD_DNN);
            String json = new JSONObject(params).toString();
//            mParamsJson = json;
        return json;
    }



    private void stopRecognize() {
        Log.i(TAG, "stopRecognize: ");
        if (mAsr != null) {
            mAsr.send(SpeechConstant.ASR_STOP, null, null, 0, 0); // 发送停止录音事件，提前结束录音等待识别结果
        }
    }


    //唤醒就回调
    private EventListener wpListener = (name, params, data, offset, length) -> {
//            Log.i(TAG, String.format("event: name=%s, params=%s", name, params));
        //唤醒成功
        if (name.equals("wp.data")) {
            try {
                JSONObject json = new JSONObject(params);
                int errorCode = json.getInt("errorCode");
                if (errorCode == 0) {
                    //唤醒成功
//                        startRecognize();
                    /*String msg = "唤醒成功";
                    toast(msg);*/
                    stopWakeup();
                    type = 1;
                    playMusic(R.raw.nihao);
                } else {
                    //唤醒失败
//                        toast("唤醒失败");
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        } else if ("wp.exit".equals(name)) {
            //唤醒已停止
            Log.i(TAG, "onEvent: 唤醒已停止");
//                toast("唤醒已停止");

        }
    };

    private void toast(String msg) {
        if (mToast == null) {
            mToast = Toast.makeText(mContext, "", Toast.LENGTH_SHORT);
        }
        mToast.setText(msg);
        mToast.show();

    }

    //识别就回调
    private EventListener asrListener = new EventListener() {

        private String[] mResults;
        private RecogResult mRecogResult;

        @Override
        public void onEvent(String name, String params, byte[] data, int offset, int length) {
//            Log.i(TAG, String.format("event: name=%s, params=%s", name, params));
            if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_READY)) {
                // 引擎就绪，可以说话，一般在收到此事件后通过UI通知用户可以说话了
                Log.i("LFX", "asrListener: 引擎就绪，可以说话");
            } else if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_PARTIAL)) {
                type = 0;
                mRecogResult = RecogResult.parseJson(params);
                // 临时识别结果, 长语音模式需要从此消息中取出结果
                mResults = mRecogResult.getResultsRecognition();
            }
            if (name.equals(SpeechConstant.CALLBACK_EVENT_ASR_FINISH)) {
                stopRecognize();
                type = 0;
                if (mRecogResult == null || mRecogResult.hasError()) {
//                    toast("识别错误");
                    playMusic(R.raw.sorry);
                } else {
                    String result = mResults[0];
                    toast("识别结果：" + result);
                    AppManager.getInstance(mContext).notifySpeechPinYinResult(result);
                }
                mRecogResult = null;
            }
        }
    };



    public void playMusic(int resId) {
        mp = MediaPlayer.create(mContext, resId);
        mp.start();
        mp.setOnCompletionListener(mediaPlayer -> {
            notifyPlayCompletion();
            mp.release();
        });
        mp.setOnErrorListener((mediaPlayer, i, i1) -> notifyPlayError());
    }

    private void notifyPlayCompletion() {
        if (type == 1) {
            startRecognize();
        } else {
            startWakeup();
        }
    }
    private boolean notifyPlayError() {
        return true;
    }

}
